package service

import (
	"errors"
	"github.com/go-admin-team/go-admin-core/sdk/service"
	"gorm.io/gorm"
	"tuowei.com/app/admin/models"
	"tuowei.com/app/admin/service/dto"
	"tuowei.com/common/actions"
	cDto "tuowei.com/common/dto"
	"tuowei.com/pkg/xlog"
)

type SysStudent struct {
	service.Service
}

// GetPage 获取SysStudent列表
func (e *SysStudent) GetPage(c *dto.SysStudentGetPageReq, p *actions.DataPermission, list *[]models.SysStudent, count *int64) error {
	var err error
	var data models.SysStudent
	tx := e.Orm.Preload("College").
		Preload("CityDept").Preload("AreaPoint").Preload("TeachRecommenders").Preload("Recommenders").Preload("ProvinceRegion").
		Preload("RegionalManagers").Preload("RegionalManager").Preload("AdmissionsOfficer").
		Preload("OfflineOrders.Course").
		Scopes(
			cDto.MakeCondition(c.GetNeedSearch()),
			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
		).Table(data.TableName())
	if c.From > 0 {
		switch c.From {
		case 1:
			tx = tx.Where("recommender = 0").Where("teach_recommender = 0")
		case 2:
			tx = tx.Where("recommender > 0")
		case 3:
			tx = tx.Where("teach_recommender > 0")
		}
	}
	//// 邀请人信息
	if c.Inviter != "" {
		// 获取教师和学生的id
		teacherIds := make([]int, 0)
		e.Orm.Table(models.SysUser{}.TableName()).Where("nick_name = ?", c.Inviter).Pluck("user_id", &teacherIds)
		studentIds := make([]int, 0)
		e.Orm.Table(models.SysStudent{}.TableName()).Where("name = ?", c.Inviter).Pluck("id", &studentIds)
		if len(teacherIds) > 0 && len(studentIds) == 0 {
			tx.Where("teach_recommender in (?) ", teacherIds)
		} else if len(teacherIds) == 0 && len(studentIds) > 0 {
			tx.Where("recommender in (?) ", studentIds)
		} else if len(teacherIds) > 0 && len(studentIds) > 0 {
			tx.Where("(teach_recommender in (?)) or (recommender in (?))", teacherIds, studentIds)
		}
	}
	err = tx.Find(list).Limit(-1).Offset(-1).
		Count(count).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return err
	}
	return nil
}

// Get 获取SysCourse对象
func (e *SysStudent) Get(d *dto.SysStudentById, p *actions.DataPermission, model *models.SysStudent) error {
	var data models.SysStudent

	err := e.Orm.Model(&data).
		Preload("CityDept").Preload("AreaPoint").Preload("Recommenders").Preload("ProvinceRegion").
		Preload("RegionalManagers").Preload("RegionalManager").Preload("AdmissionsOfficer").
		Scopes(
			actions.Permission(data.TableName(), p),
		).
		First(model, d.GetId()).Error
	if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
		err = errors.New("查看对象不存在或无权查看")
		xlog.Errorf("db error: %s", err)
		return err
	}

	return nil
}

func (e *SysStudent) ChangeStatus(d *dto.SysStudentById) error {
	var data models.SysStudent
	err := e.Orm.Model(&data).First(&data, d.GetId()).Error
	if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
		err = errors.New("查看对象不存在或无权查看")
		xlog.Errorf("db error: %s", err)
		return err
	}
	updateStatus := 0
	if data.Status == 1 {
		updateStatus = 0
	} else {
		updateStatus = 1
	}
	return e.Orm.Model(&data).Update("status", updateStatus).Error
}

func (e *SysStudent) Insert(c *dto.SysStudentInsertReq) (int, error) {
	var err error
	var data models.SysStudent
	var i int64
	err = e.Orm.Model(&data).Where("phone = ?", c.Phone).Count(&i).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return 0, err
	}
	if i > 0 {
		err = errors.New("学员已存在！")
		e.Log.Errorf("db error: %s", err)
		return 0, err
	}
	c.Generate(&data)
	err = e.Orm.Create(&data).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return 0, err
	}
	return data.Id, nil
}

func (e *SysStudent) UpdateBuyStatus(c *dto.SysStudentUpdateBuyStatusReq) error {
	model := models.SysStudent{}
	err := e.Orm.Model(&model).Where("id in (?)", c.Ids).Update("buy_status", c.BuyStatus).Error
	if err != nil {
		return err
	}
	return nil
	// todo
	// 如果是设置为退学状态，允许登录APP，但不涉及退学前课程服务？？？嘛意思
}

func (e *SysStudent) Excel(c *dto.SysStudentExcelReq) ([]models.SysStudent, error) {
	//model := models.SysStudent{}
	offlineOrderBuyerIds := make([]int, 0)
	materialOrderBuyerIds := make([]int, 0)
	onlineOrderBuyerIds := make([]int, 0)
	e.Orm.Model(models.OfflineOrder{}).Distinct("buyer_id").
		Where("pay_at  between ? and ?", c.StartTime, c.EndTime).
		Pluck("buyer_id", &offlineOrderBuyerIds)
	e.Orm.Model(models.OnlineOrder{}).Distinct("buyer_id").
		Where("pay_at  between ? and ?", c.StartTime, c.EndTime).
		Pluck("buyer_id", &onlineOrderBuyerIds)
	e.Orm.Model(models.MaterialOrder{}).Distinct("buyer_id").
		Where("pay_at  between ? and ?", c.StartTime, c.EndTime).
		Pluck("buyer_id", &materialOrderBuyerIds)
	offlineOrderBuyerIds = append(offlineOrderBuyerIds, materialOrderBuyerIds...)
	offlineOrderBuyerIds = append(offlineOrderBuyerIds, onlineOrderBuyerIds...)
	lists := make([]models.SysStudent, 0)
	if len(offlineOrderBuyerIds) == 0 {
		return lists, errors.New("无数据")
	}
	err := e.Orm.Preload("AreaPoint").Preload("College").Preload("OfflineOrders.Course").Where("id in (?)", offlineOrderBuyerIds).Find(&lists).Error
	return lists, err
	// 如果是设置为退学状态，允许登录APP，但不涉及退学前课程服务？？？嘛意思
}

func (e *SysStudent) Update(c *dto.SysStudentUpdateReq) error {
	var err error
	var model = models.SysStudent{}
	var i int64
	err = e.Orm.Model(&model).Where("phone = ?", c.Phone).Where("id <> ?", c.Id).Count(&i).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return err
	}
	if i > 0 {
		err = errors.New("学员已存在！")
		e.Log.Errorf("db error: %s", err)
		return err
	}
	c.Generate(&model)
	db := e.Orm.Save(&model)
	err = db.Error
	if err != nil {
		e.Log.Errorf("Service UpdateStudent error:%s", err)
		return err
	}
	if db.RowsAffected == 0 {
		return errors.New("无权更新该数据")
	}
	return nil
}

// GetListByClassId 获取某个班级的学生列表
func (e *SysStudent) GetListByClassId(c *dto.GetListByClassIdReq, list *[]models.SysStudent, count *int64) error {
	var err error
	var data models.SysStudent
	tx := e.Orm.Preload("College").
		Preload("CityDept").Preload("AreaPoint").Preload("Recommenders").Preload("ProvinceRegion").
		Preload("RegionalManagers").Preload("RegionalManager").Preload("AdmissionsOfficer").
		Preload("OfflineOrders.Course").
		Scopes(
			cDto.MakeCondition(*c),
			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
		).Table(data.TableName())

	err = tx.Find(list).Limit(-1).Offset(-1).
		Count(count).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return err
	}
	return nil
}

//GetNoClassStudents get students lists which has not been divided into any class !

func (e *SysStudent) GetNoClassStudents(c *dto.GetNoClassStudentListReq, list *[]models.SysStudent, count *int64) error {
	var err error
	var data models.SysStudent
	tx := e.Orm.Preload("College").
		Preload("CityDept").Preload("AreaPoint").Preload("Recommenders").Preload("ProvinceRegion").
		Preload("RegionalManagers").Preload("RegionalManager").Preload("AdmissionsOfficer").
		Preload("OfflineOrders.Course").
		Where("(class_id  = 0 )").
		Scopes(
			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
		).Table(data.TableName())

	err = tx.Find(list).Limit(-1).Offset(-1).
		Count(count).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return err
	}
	return nil
}
